//Pietras93OS
//Keyboard
//pietras93@gmail.com
//

#include <system.h>

volatile char* buffer; //For storing strings
volatile char* buffer2;
volatile int kb_count = 0; //Position in buffer
volatile int gets_flag = 0;
unsigned short ltmp;
volatile int shift_flag=0;
volatile int caps_flag=0;
unsigned char kbdus[128] =
{
    0,  27, '1', '2', '3', '4', '5', '6', '7', '8',	/* 9 */
  '9', '0', '-', '=', '\b',	/* Backspace */
  '\t',			/* Tab */
  'q', 'w', 'e', 'r',	/* 19 */
  't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',		/* Enter key */
    0,			/* 29   - Control */
  'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',	/* 39 */
 '\'', '`',   0,		/* Left shift */
 '\\', 'z', 'x', 'c', 'v', 'b', 'n',			/* 49 */
  'm', ',', '.', '/',   0,					/* Right shift */
  '*',
    0,	/* Alt */
  ' ',	/* Space bar */
    0,	/* Caps lock */
    0,	/* 59 - F1 key ... > */
    0,   0,   0,   0,   0,   0,   0,   0,
    0,	/* < ... F10 */
    0,	/* 69 - Num lock*/
    0,	/* Scroll Lock */
    0,	/* Home key */
    0,	/* Up Arrow */
    0,	/* Page Up */
  '-',
    0,	/* Left Arrow */
    0,
    0,	/* Right Arrow */
  '+',
    0,	/* 79 - End key*/
    0,	/* Down Arrow */
    0,	/* Page Down */
    0,	/* Insert Key */
    0,	/* Delete Key */
    0,   0,   0,
    0,	/* F11 Key */
    0,	/* F12 Key */
    0,	/* All other keys are undefined */
};

void keyboard_handler(struct regs *r)
{
    unsigned char scancode;

    scancode = inportb(0x60);

    switch (scancode)
    {
           case 0x3A:
                /* CAPS_LOCK LEDS */
                outportb(0x60,0xED);
                ltmp |= 4;
                outportb(0x60,ltmp);
                
                if(caps_flag)
                caps_flag=0;
                else
                caps_flag=1;
                break;
           case 0x45:
                /* NUM_LOCK LEDS */
                outportb(0x60,0xED);
                ltmp |= 2;
                outportb(0x60,ltmp);
                break;
           case 0x46:
                /* SCROLL_LOCK LEDS */
                outportb(0x60,0xED);
                ltmp |= 1;
                outportb(0x60,ltmp);
                break;
           //case 60: /* F12 */
                //reboot();
             //   break;
           default:
                break;
    }

    if (scancode & 0x80)
    {
        //Key release
        
        //Left and right shifts
        if (scancode - 0x80 == 42 || scancode - 0x80 == 54)
			shift_flag = 0;
    } else {   
        //Keypress (normal)
        
        //Shift
        if (scancode == 42 || scancode == 54)
		{
			shift_flag = 1;
			return;
		}
        
        //Gets()
        if(kbdus[scancode] == '\n')
        {
             if(gets_flag == 0) do_gets();
             gets_flag++;
             for(;kb_count; kb_count--)
                  buffer[kb_count] = 0;              
        } else {
             if(kbdus[scancode] == '\b')
             {
                  if(kb_count)
                  buffer[kb_count--] = 0;
             } else {
                  buffer[kb_count++] = kbdus[scancode];
             }
                  
        } 
        
        //Print key
        putch(kbdus[scancode]);
        
        return;
    }

}

/* Installs the keyboard handler into IRQ1 */
void keyboard_install()
{
    irq_install_handler(1, keyboard_handler);
	puts("Keyboard instlled!");
}

unsigned char getch()
{
     unsigned char getch_char;
     
     if(kbdus[inportb(0x60)] != 0) //Not empty
     outportb(0x60,0xf4); //Clear buffer
     
     while(kbdus[inportb(0x60)] == 0); //While buffer is empty
     getch_char = kbdus[inportb(0x60)];
     outportb(0x60,0xf4); //Leave it emptying
     return getch_char;
}

char* gets()
{ 
     gets_flag = 0;
     while(gets_flag == 0);
     return (char*)buffer2;
}

/*static*/void do_gets()
{
     buffer[kb_count++] = 0; //Null terminated biatch!
     for(;kb_count; kb_count--)
     {
          buffer2[kb_count] = buffer[kb_count];
     }
     return;
}
